home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / DOS / PG / CHART.ZIP / CSUB2.86 < prev    next >
Encoding:
Text File  |  1992-11-20  |  26.7 KB  |  949 lines

  1.  
  2.         ;xchange functionality of box to/from decision/simple function
  3.  
  4. xchange:
  5.         call get_current_box    ;get current box pointer
  6.         mov b chart_flag,4    ;set chart entry flag
  7.         xor ax,ax    ;clear yes route
  8.     es    cmp w[di+no],ax    ;is box decision box?
  9.         je >b1    ;convert to decision box if not
  10.     es    cmp w[di+no],1    ;is route for box, yes route
  11.         je >b3    ;convert to function box if not
  12.  
  13.         ;check if there is a yes route
  14.  
  15.     es    cmp w[di+yes],ax    ;is there?
  16.         je >b2    ;swap route to yes if not
  17.     es    mov ax,w[di+yes]    ;load yes route
  18.     es    xchg ax,w[di+no]    ;swap for no route
  19.     es    mov w[di+yes],ax    ;store yes route
  20.         stc    ;goto start of chart loop
  21.         ret    ;exit
  22.  
  23.         ;make decision box simple function box
  24.  
  25. b2:
  26.     es    xchg w[di+no],ax    ;clear no route
  27.     es    mov w[di+yes],ax
  28.         stc    ;exit
  29.         ret
  30.  
  31.         ;move yes route to no
  32.  
  33. b3:
  34.     es    xchg w[di+yes],ax    ;load yes route
  35.         cmp ax,bp    ;is route outstanding?
  36.         je >c1    ;exit if it is
  37.         or ax,ax    ;is there a yes route?
  38. if ne    es    mov w[di+no],ax
  39.         stc    ;exit
  40.         ret
  41.  
  42.         ;make current box decision box
  43.  
  44. b1:
  45.     es    or w[di+yes],ax    ;is there a route?
  46. if ne    es    mov w[di+no],1    ;make simple box decision box
  47. c1:
  48.         stc    ;goto start of chart loop
  49.         ret    ;exit
  50.  
  51.         ;relinquish branch route option
  52.  
  53. relinquish:
  54.         cmp w key_option,13*2    ;has route been chosen?
  55.         je >a1    ;relinquish route if it has
  56.         mov b new_chart,0    ;indicate chart changed
  57.         mov bx,w first_branch_route    ;copy first branch route
  58.         mov w route,bx
  59.         cmp w branch_route_count,1    ;is there more than one branches?
  60.         je >a1    ;relinquish route if not
  61.  
  62.         ;prompt for which route to relinquish
  63.  
  64.         call write_message    ;write prompt to buffer
  65.         db 'Choose route to unlink',0
  66.         mov w key_option,13*2    ;store key option
  67.         mov w box_save,1    ;indicate flowchart not dormant
  68.         mov w insert_mode,2
  69.         mov w current_route,bx    ;set current route
  70.         call write_route_stem    ;set route stem string
  71.         mov b chart_flag,1    ;set chart entry flag
  72.         stc    ;exit to chart loop
  73.         ret
  74.  
  75.         ;check if deleting route will split up chart
  76.  
  77. a1:
  78.         mov bx,w route    ;load route to be severed
  79.         call store_save_route    ;save and clear route
  80.         jb >c1    ;reset variables if route is terminator
  81.         call will_box_be_missed    ;will deleted route split up chart?
  82.         jc >c1    ;exit if it will
  83.  
  84.         ;redirect current boxes leading neighbour box
  85.  
  86.         mov ax,dx    ;load box to redirect
  87.         xor bx,bx    ;load offset to neighbour route
  88.         call get_box_par    ;get neighbour box
  89.         or ax,ax    ;is there one?
  90.         je >c1    ;leave box if not
  91.         mov ax,dx    ;load box to redirect
  92.         mov dx,si    ;exchange destination box for link box
  93.         call store_box_par    ;redirect neighbour box
  94.  
  95.         ;clear branch from current route of current box
  96.  
  97. c1:
  98.         xor ax,ax    ;load zero
  99.         mov w branch_route_count,ax    ;clear branch count
  100.         mov w box_save,ax    ;indicate flowchart is dormant
  101.         mov w insert_mode,ax
  102.         mov w key_option,ax    ;clear key option indicator
  103.         mov b message,al    ;clear bottom line message buffer
  104.         mov b chart_flag,4    ;set chart entry flag
  105.         stc    ;exit to chart loop
  106.         ret
  107.  
  108.         ;save and clear current route
  109.  
  110. store_save_route:
  111.         call get_current_box    ;get box to which it is linked
  112.         xor dx,dx    ;exchange zero for box of route
  113.     es    cmp w[di+no],dx    ;is box decision box?
  114.         je >a1    ;clear route if not
  115.         cmp bx,no    ;is current route 'no' route?
  116. if e        inc dx    ;indicate it is but without 'no' route
  117. a1:
  118.     es    xchg dx,w[di+bx]    ;save it
  119.         cmp dx,first_box    ;is route to exit from sub_chart?
  120.         ret    ;exit
  121.  
  122.         ;check if any references from current box to start of current chart
  123.  
  124.         ;find link from ax:box to dx:box
  125.  
  126. c1:
  127.         mov sp,w temp1    ;restore stack
  128.         ret    ;exit
  129. find_box_to_box:
  130.         mov w temp1,sp    ;save stack pointer
  131. b1:
  132.         call get_box    ;get total real routes
  133.         mov bx,no    ;load offset to no route
  134.         mov si,ax    ;save this box id
  135.         cmp ax,dx    ;is search box in path?
  136.         je c1    ;exit if it is
  137.  
  138.         ;save other route if two routes
  139.  
  140. a1:
  141.     es    mov ax,w[di+bx]    ;load route
  142.         cmp ax,first_box    ;is it a box route?
  143.         jb >a2    ;move to next route if not
  144.         cmp ax,dx    ;does it point to neighbour box?
  145.         je c1    ;delete box/route (exit)
  146.  
  147.         ;check if box of route has been checked
  148.  
  149.         push ax,bx    ;save box id
  150.         mov bx,box_temp    ;load offset to box variable
  151.         call get_box_par    ;get box id
  152.         pull bx    ;restore offset to route
  153.         or ah,ah    ;has box been checked
  154. if e        pull ax    ;clear from stack if it has
  155. a2:
  156.         dec bx,bx    ;move to next route
  157.         jne a1    ;check next route if not finished
  158.  
  159.         ;check if anymore boxes on stack
  160.  
  161.     es    mov b[di+box_temp+1],bl    ;indicate this box checked
  162.         cmp sp,w temp1    ;anymore routes?
  163.         stc    ;indicate error
  164.         je ret    ;exit with error if not
  165.         pull ax    ;load next current box
  166.         jmp b1    ;check for any references to current box
  167.  
  168.         ;check if route from current box to box:dx is only route
  169.  
  170. will_box_be_missed:
  171.         push dx,bp    ;save box of route and current box
  172.         call move_to_first_box    ;move to first box in chart
  173.         call reset_chart_flags_hi    ;flag all boxes unchecked
  174.         mov ax,bp    ;load first box in chart
  175.         pull bp,dx    ;restore boxes
  176.         call find_box_to_box    ;check if alternative route to box
  177.         jnc ret    ;exit if found
  178.  
  179.         ;restore link to neighbour box
  180.  
  181. e1:
  182.         mov bx,w route    ;load route offset
  183.         call store_current_box_par    ;restore route in dx to current box
  184.         call clear_line    ;clear bottom line
  185.         call writexy    ;write error message
  186.         db 30,24
  187.         db 'Chart will be split',0
  188.         call key    ;wait for keypress
  189.         stc    ;indicate error
  190.         ret    ;exit
  191.  
  192.         ;insert box option
  193.  
  194. insert_box:
  195.         call get_neighbour_route    ;get connecting route
  196.         mov dx,w next_box    ;load new box
  197.         jnc >a1    ;point following box to new box if no
  198.             ;leading neighbour box
  199.         call store_box_par    ;point route of neighbour box to new box
  200.         xor bx,bx    ;load previous route offset
  201. a1:
  202.         call store_current_box_par    ;make new box neighbour box
  203.  
  204.         ;create new box and point it to leading neighbour box of current box
  205.  
  206.         call make_box    ;create box
  207.         stosw    ;make new box neighbour of neighbour of
  208.             ;current box
  209.         mov bx,parent    ;get parent route of neighbour box
  210.         call get_current_box_par
  211.     es    mov w[di+parent-2],ax    ;make new box parent of it
  212.         and b box_made,1    ;indicate box made
  213.         mov w box_save,bp    ;inserted route to current box
  214.  
  215.         ;initialise variables for last insert operation
  216.  
  217.         call write_message    ;write bottom line message
  218.         db 'Choose route from inserted box to link',0
  219.         mov w insert_mode,1    ;store insert mode flag
  220.         mov w link_box,dx    ;store new box
  221.         mov b chart_flag,2    ;set chart entry flag
  222.         stc    ;exit to chart loop
  223.         ret
  224.  
  225.         ;get connecting route of cuurent boxes leading neighbour box
  226.  
  227. get_neighbour_route:
  228.         xor bx,bx    ;load previous box element offset
  229.         call get_current_box_par    ;get leading neighbour box
  230.         or ax,ax    ;is there one?
  231.         je ret    ;exit if not
  232.         call get_routes    ;get current box routes
  233. a1:
  234.         add bx,2    ;move to next route
  235.         cmp w[bx+routes],bp    ;does route point to current box?
  236.         jne a1    ;check next route if not
  237.         stc    ;indicate there is a neighbour box
  238.         ret    ;exit
  239.  
  240.         ;single option
  241.  
  242. single:
  243.         mov b chart_flag,4    ;store chart entry flag
  244.         stc    ;exit to chart loop
  245.         ret
  246.  
  247.         ;yes route option
  248.  
  249. yes_option:
  250.         mov dx,yes    ;load single/yes route indicator
  251. other_options:
  252.         mov w current_route,dx    ;set current route
  253.         mov b route_string,'('    ;store bracket indicators
  254.         mov b route_string+1,al    ;save route character
  255.         mov b route_string+2,')'
  256.         mov b chart_flag,1    ;store chart entry flag
  257.         stc    ;exit to chart loop
  258.         ret
  259.  
  260.         ;no route option
  261.  
  262. no_option:
  263.         mov dx,no    ;load route element offset
  264.         jmp other_options    ;set current route
  265.  
  266.         ;no route option
  267.  
  268. no_route:
  269.         inc bx    ;increment route marker
  270.  
  271.         ;yes route option
  272.  
  273. yes_route:
  274.         inc bx    ;increment route marker
  275.         shl bx,1    ;convert route marker to offset
  276.  
  277. move_to_route:
  278.         mov ax,bp    ;load current box
  279.         xor bp,bp    ;indicate moving to route
  280.         call get_route3    ;get box of route
  281.         mov bp,ax
  282.  
  283.         ;set chart entry flag and exit
  284.  
  285.         mov b chart_flag,1    ;set chart entry flag
  286.         cmp w box_save,0    ;is flowchart dormant?
  287. if e        mov b chart_flag,4    ;set chart entry flag
  288.         stc    ;exit to chart loop
  289.         ret
  290.  
  291.         ;get box of route and save state of subchart stack
  292.  
  293. get_route:
  294.         push w sub_stack    ;save stack pointer
  295.         call get_route2    ;get box of route
  296.         pull w sub_stack    ;restore stack pointer
  297.         cmp ax,first_box    ;is route void?
  298. if b        xor ax,ax    ;indicate no route if it is
  299.         ret    ;exit
  300.  
  301.         ;get box of route in bx of box in ax
  302.  
  303. get_route2:
  304.         cmp bx,1    ;is there?
  305.         ja get_route3    ;get next box of route if there is
  306. a1:
  307.         xor ax,ax    ;indicate no route
  308.         ret    ;exit
  309.  
  310.         ;check if route is subchart terminating route
  311.  
  312. get_route3:
  313.         cmp bx,first_box    ;is route direct?
  314.         jb >a2    ;get return box route if not
  315.         mov ax,bx    ;load box route
  316.         ret    ;exit
  317. a2:
  318. ;        mov w levels,1    ;clear level count
  319.         push bx,cx,dx,di,bp,es    ;save registers
  320.         mov dx,ax    ;load current box
  321.         mov cx,bx    ;load route of box
  322.         or bp,bp    ;moving to route?
  323.         jne >b3    ;leave parameters if not
  324.         call get_box_par    ;get box from current route
  325.         mov bx,ax    ;save it
  326.  
  327.         ;check if current box is at the end of a subchart
  328.  
  329. b1:
  330.         cmp ax,first_box    ;is it?
  331.         jae >b2    ;exit if not
  332.         mov ax,dx    ;load current box
  333. b3:
  334. ;        inc w levels    ;increment level count
  335.         call get_box    ;get current box pointer
  336.  
  337.         ;check if subchart is copied from elsewhere
  338.  
  339.         cmp w sub_stack,top_stack    ;are there any subcharts on stack
  340.         je >a1    ;load route from parent box if not
  341.         call copy_substack    ;copy stack data
  342.         mov ax,w subchart_parent    ;load parent of subchart on stack
  343.     es    cmp ax,w[di+parent]    ;is subchart copied?
  344.         jne >a1    ;load route from parent box if not
  345.  
  346.         ;copy box from parent of copied subchart
  347.  
  348.         mov ax,w subchart_box    ;load step parent box
  349.         mov dx,ax    ;save it
  350.         call get_box_par    ;get route of current box of parent box
  351.         add w sub_stack,4    ;clear copied subchart from stack
  352.         jmp >a2    ;check parent route
  353.  
  354.         ;make box of parent of route of current box, current box
  355.  
  356. a1:
  357.     es    mov ax,w[di+parent]    ;load parent box of subchart
  358.         mov dx,ax    ;save it
  359.         call get_box_par    ;get its box
  360.         mov bx,ax    ;save offset to route
  361.  
  362.         ;check if there is a box from parent route
  363.  
  364. a2:
  365.         cmp ax,1    ;is there?
  366.         ja b1    ;check if it isn't
  367.         mov ax,dx    ;load parent box of route
  368. ;        jmp >b3    ;exit
  369.  
  370.         ;move to last level of new box
  371.  
  372. b2:
  373. ;        cmp w key_option,14*2    ;is user choosing a route for parent box
  374. ;        je >b3    ;exit if yes
  375. ;a3:
  376. ;        dec w levels    ;is pointer at previous level?
  377. ;        je >b3    ;exit if it is
  378. ;        mov bx,child    ;load child subchart element offset
  379. ;        mov dx,ax    ;save box
  380. ;        call get_box_par    ;is there a child subchart?
  381. ;        or ax,ax
  382. ;        je >a2    ;exit if not
  383. ;        mov bp,dx    ;load parent box
  384. ;        call down2    ;move down a level
  385. ;        mov ax,bp    ;load child box
  386. ;        jmp a3    ;decrement level count
  387. ;a2:
  388. ;        mov ax,dx    ;restore box
  389. b3:
  390.         pull es,bp,di,dx,cx,bx    ;restore registers
  391.         ret    ;exit
  392.  
  393.         ;copy subchart data from subchart stack
  394.  
  395. copy_substack:
  396.         push ax,si,es    ;save box of subchart
  397.         les si,w sub_stack    ;load subchart stack pointer
  398.     es    lodsw    ;load subchart box
  399.         mov w subchart_box,ax    ;save it
  400.     es    lodsw    ;copy subchart parent (this may not be
  401.         mov w subchart_parent,ax    ;the same as subchart box if subchart is
  402.             ;copied)
  403.         pull es,si,ax    ;restore box of subchart
  404.         ret    ;exit
  405.  
  406.         ;write box to screen
  407.  
  408. write_box:
  409.         call get_route    ;get box of route along stem
  410.         mov dx,ax
  411.         mov b this_box,cl    ;store box parameter
  412.  
  413.         ;copy box descripter string to buffer
  414.  
  415.         cmp cx,1    ;is box centre box?
  416.         je >a1    ;clear other routes if it is
  417.         mov es,ax,cs    ;copy code segment
  418.         mov di,o descripter_string    ;load offset to descripter string buffer
  419.         mov ax,dx    ;load box number
  420.         call get_box_descripter    ;copy box descripter string to buffer
  421.         push cx    ;save string size
  422.         rep
  423.         movsb    ;copy box descripter string
  424.         mov ds,ax,cs    ;restore data segment register
  425.         pull w descripter_count    ;store size of descripter
  426.  
  427.         ;copy box number to buffer
  428.  
  429.         mov di,o number_buffer    ;load offset to buffer
  430.         mov ax,': '    ;load trailing separator
  431.         stosw    ;store it at end/start of string
  432.         mov ax,dx    ;load box number
  433.         sub ax,first_box-1
  434.         call store_number2    ;write it to end of buffer
  435.  
  436.         ;clear other box routes
  437.  
  438. a1:
  439.         mov cx,2    ;load loop count
  440.         xor si,si    ;clear offset
  441.         mov ax,si
  442. a1:
  443.         mov w[si+other_box_routes],ax    ;clear other routes
  444.         mov w[si+other_boxes],ax    ;clear other box routes for this box
  445.         add si,2    ;increment offset
  446.         loop a1    ;decrement loop count
  447.  
  448.         ;add any higher level subcharts to descripter string
  449.  
  450.         mov w box_route,bx    ;save route
  451.         mov ax,dx    ;load box being written
  452.         mov bx,parent    ;load offset to box parent
  453. a1:
  454.         call get_box_par    ;get parent of it
  455.         or ax,ax    ;is there one?
  456.         je >b1    ;copy path string to buffer if not
  457.         mov dx,ax    ;save parent box
  458.  
  459.         ;add parent box number to path string
  460.  
  461. a2:
  462.         mov al,':'    ;load separator
  463.         stosb    ;write it to end of buffer
  464.         mov ax,dx    ;load parent box
  465.         sub ax,first_box-1    ;calculate box number
  466.         call store_number2    ;add it to end/start of path string
  467.         jc >b1    ;copy path string if buffer full
  468.         mov ax,dx    ;load parent of box
  469.         jmp a1    ;check if it has a parent
  470.  
  471.         ;copy path string to temporary buffer
  472.  
  473. b1:
  474.         mov si,di    ;save offset to end of buffer
  475.         dec si
  476.         sub di,o number_buffer    ;calculate size of string
  477.         mov cx,di
  478.         mov di,o s    ;load offset to buffer
  479.  
  480.         ;copy string
  481.  
  482. a1:
  483.         std    ;read backwards
  484.         lodsb    ;load character from path string
  485.         cld    ;write forwards
  486.         stosb    ;write character to buffer
  487.         loop a1    ;decrement loop count
  488.  
  489.         ;copy descripter string to end of path string
  490.  
  491.         mov si,o descripter_string    ;load offset to string
  492.         mov cx,w descripter_count    ;load length of it
  493.         rep
  494.         movsb    ;copy descripter string to end of buffer
  495.         sub di,o s    ;calulate length of descripter string
  496.         mov w descripter_count,di    ;save it
  497.  
  498.         ;load following box for centre box
  499.  
  500.         cmp b this_box,1    ;is box centre box?
  501.         jne >b1    ;check if it is leading box if not
  502.         mov dx,w box    ;load following box
  503.         test b err,1    ;is there a following box?
  504.         jne >a2    ;store it if there is
  505.  
  506.         ;get following box from centre box
  507.  
  508.         mov bx,w follow_route    ;load following route
  509.         mov ax,bx    ;indicate no following box
  510.         or bx,bx    ;is there one?
  511.         je >a1    ;clear follow box if not
  512.         mov ax,dx    ;load following box
  513.         call get_box_par    ;get box of route
  514.         mov bx,ax
  515.         mov ax,dx    ;get following box
  516.         call get_route
  517. a1:
  518.         mov dx,ax    ;load box
  519. a2:
  520.         mov w follow_box,dx    ;store following box
  521.         jmp >b2    ;get other routes
  522.  
  523.         ;check if box being written is leading box
  524.  
  525. b1:
  526.         cmp b this_box,4    ;is box leading box?
  527.         jne >b1    ;check if it is current box if not
  528.         mov w follow_box,bp    ;store current box as following box
  529.         jmp >b2    ;get other routes
  530.  
  531.         ;get following box of following box
  532.  
  533. b1:
  534.         call get_follow_box    ;get following box
  535.         or ax,ax    ;is there a box?
  536. if e        mov ax,-2    ;indicate no following box
  537.         mov w follow_box,ax    ;save following box
  538.  
  539.         ;get any other routes from this box
  540.  
  541. b2:
  542.         mov w route_follow,0    ;indicate no following route
  543.         mov si,yes    ;load offset to box element
  544.         xor di,di    ;load offset to other routes store
  545.         mov cx,2    ;load route/loop count
  546.  
  547.         ;get box of route of box
  548.  
  549. b1:
  550.         mov ax,w box_route    ;load box of route
  551.         mov dx,ax
  552.         mov bx,si    ;load box element
  553.         call get_box_par    ;get box of box route
  554.         mov bx,ax
  555.         mov ax,dx    ;load route of box
  556.         call get_route    ;get box of route
  557.         mov dx,ax
  558.  
  559.         ;check if route is not following box
  560.  
  561.         or dx,dx    ;is there a box on this route?
  562.         je >a1    ;decrement loop count if not
  563.         cmp si,w main_route    ;is route selected route?
  564.         je >a3    ;check insert mode if it is
  565.         cmp dx,w follow_box    ;is route to following box?
  566.         jne >a2    ;store other route if not
  567.         cmp w insert_mode,2    ;is new box route being selected?
  568.         jne >a4    ;save follow route if not
  569.         cmp b this_box,1    ;is box centre box?
  570.         jne >a4    ;save follow route if not
  571.  
  572.         ;copy box route data
  573.  
  574. a2:
  575.         mov w[di+other_boxes],dx    ;store follow box
  576.         mov w[di+other_box_routes],si    ;store box route
  577.         add di,2    ;move to next element
  578.         jmp >a1    ;decrement loop count
  579.  
  580.         ;save following route
  581.  
  582. a3:
  583.         cmp b insert_mode,2    ;is route being selected for insert box?
  584.         je >a4    ;store following route if it is
  585.         cmp b this_box,1    ;is box centre box?
  586.         je >a1    ;decrement loop count if it is
  587. a4:
  588.         mov w route_follow,si    ;store route element
  589.         mov w follow_box,-2
  590. a1:
  591.         add si,2    ;move to next route
  592.         loop b1    ;decrement loop count
  593.  
  594.         ;store character for left route of stem
  595.  
  596.         mov bx,w other_box_routes    ;load route offset
  597.         add bx,10    ;load route
  598.         mov bx,w[bx+options_table]    ;load offset to option string
  599.         mov al,b[bx]    ;load route option character
  600.         cmp di,2    ;is there one route?
  601.         jne >a1    ;store route indicator if not
  602.         cmp w route_follow,0    ;is there a decision route
  603. if e        mov al,'F'    ;load forward indicator if not
  604. a1:
  605.         mov b left_route_indicator,al    ;save it
  606.  
  607.         ;split descripter string if it is longer than 3/4rs of screen width
  608.  
  609.         mov w stem_start,1    ;assume descripter string is one row
  610.         mov b split_line,0    ;indicate line not split
  611.         cmp w descripter_count,60    ;is descripter string bigger than 3/4rs
  612.         jbe >c1    ;check if there is another route if not
  613.         mov si,w descripter_count    ;calculate offset to half of string
  614.         shr si,1
  615.         mov cx,si
  616.         add si,o s
  617.         mov b hyphen,0    ;indicate end of line not hyphenated
  618.         mov b split_line,0ffh    ;indicate line split
  619.  
  620.         ;calculate quarter of length of half of string
  621.  
  622.         shr cx,1    ;divide half by four
  623.         mov ax,cx    ;save offset incase line can't be split
  624.         shr ax,1
  625.         mov di,si    ;save offset to descripter
  626.         add si,ax
  627. a1:
  628.         dec si    ;decrement offset
  629.         cmp b[si],' '    ;can line be split without hyphenating?
  630.         loopne a1    ;decrement loop count
  631.  
  632.         ;restore offset to line half if can't be hyphenated
  633.  
  634.         je >b1    ;save offset if it can
  635.         mov si,di    ;restore offset to line half
  636.         inc si    ;move to last character
  637.         cmp b[si],' '    ;will hypenation look odd?
  638.         je >b1    ;leave offset if it will
  639.         dec si    ;restore offset
  640.         mov b hyphen,'-'    ;indicate line to be hyphenated
  641. b1:
  642.         mov w split_line+1,si    ;save offset to end of first half
  643.  
  644.         ;create string for left other route (if there is one)
  645.  
  646. c1:
  647.         mov b left_route,0    ;indicate no left route stem
  648.         mov si,o other_boxes    ;load second route flag
  649.         cmp w[si],0    ;is there another route?
  650.         je >c1    ;check if this box is centre box if not
  651.         mov bx,w[si+obro]    ;load route element
  652.         mov di,o akey_jump+2    ;load offset to left key address
  653.         call write_akey_address    ;write jmp address for left arrow key
  654.         call get_hor_stem    ;get second route stem
  655.         mov di,o left_route    ;load offset to buffer
  656.         je >b1    ;write graphics if outstanding route
  657.  
  658.         ;copy path/descripter to left route store
  659.  
  660.         mov si,bx    ;load source offset
  661.         mov cx,dx    ;load count
  662.         dec cx    ;adjust it
  663.         rep
  664.         movsb    ;copy path/descripter
  665.         lodsb    ;load last character
  666.  
  667.         ;store graphic characters
  668.  
  669. b1:
  670.         stosb    ;store first/last character from path
  671.         mov ax,'═╞'    ;load left end stem and horz stem chrs
  672.         stosw    ;store it at end of string
  673.         mov al,b left_route_indicator    ;load left route indicator
  674.         stosb    ;store it in string
  675.         mov ax,'╣═'    ;load middle left stem characters
  676.         stosw    ;store them at end of string
  677.         mov w left_route_end,di    ;save offset to end of string
  678.  
  679.         ;check if there is a third route
  680.  
  681.         mov si,o other_boxes+2    ;load other route
  682.         cmp w[si],0    ;is there a third route?
  683.         je >c1    ;set attribute if not
  684.  
  685.         ;copy path/descripter to left route store
  686.  
  687.         dec di    ;move offset over centre graphic
  688.         mov ax,'═╬'    ;load horizontal double bar graphic
  689.         stosw    ;store graphics to string
  690.         mov si,w[si+obro]    ;load route element
  691.         shr si,1
  692.         mov al,b[si+keys+5]    ;load route indicator
  693.         mov ah,'═'    ;load graphic
  694.         stosw    ;write it with route character to buffer
  695.         mov al,'╡'    ;load graphic character
  696.         stosb    ;write it to end of string
  697.         mov al,'?'    ;load outstanding route character
  698.         stosb    ;write it to end of horizontal stem
  699.  
  700.         ;set attribute for descripter string
  701.  
  702. c1:
  703.         mov b attribute,novid    ;store normal video attribute
  704.         cmp b this_box,1    ;is box centre box?
  705. if e        mov b attribute,revid    ;store reverse video attribute
  706.  
  707.         ;check if descripter string is hyphenated
  708.  
  709.         mov si,o s    ;load offset to string
  710.         cmp b split_line,0    ;is line split?
  711.         je >b1    ;write descripter string if not
  712.         inc w stem_start    ;add it to stem length
  713.         mov cx,w split_line+1    ;load offset to end of second half
  714.         sub cx,si    ;calculate length of first half
  715.         sub w descripter_count,cx    ;calculate length of second half
  716.  
  717.         ;position cursor for string and write descripter string to screen
  718.  
  719.         mov dl,80    ;load max screen width
  720.         sub dl,cl    ;subtract length of string
  721.         shr dl,1    ;half it
  722.         mov dh,b cursor_pos+1    ;load cursor row
  723.         inc b cursor_pos+1    ;increment it
  724.         call cursor    ;position cursor
  725. a1:
  726.         lodsb    ;load character from string
  727.         call write_chr    ;write it to screen
  728.         loop a1    ;decrement loop count
  729.  
  730.         ;write hyphen character if line is hyphenated
  731.  
  732.         mov al,b hyphen    ;load hyphen flag
  733.         or al,al    ;is it?
  734.         je >a1    ;increment offset to second half if not
  735.         call write_chr    ;write hyphen character to screen
  736.         dec si    ;adjust offset to descripter string
  737.         inc w descripter_count    ;adjust count
  738. a1:
  739.         inc si    ;move offset past space
  740.         dec w descripter_count
  741.  
  742.         ;position cursor for string and write descripter string to screen
  743.  
  744. b1:
  745.         mov cx,w descripter_count    ;load length of string
  746.         mov dl,80    ;load max screen width
  747.         sub dl,cl    ;subtract length of string
  748.         shr dl,1    ;half it
  749.         mov dh,b cursor_pos+1    ;load cursor row
  750.         inc b cursor_pos+1    ;increment it
  751.         call cursor    ;position cursor
  752. a1:
  753.         lodsb    ;load character from string
  754.         call write_chr    ;write it to screen
  755.         loop a1    ;decrement loop count
  756.  
  757.         ;store normal video attribute
  758.  
  759.         mov b attribute,novid    ;store normal video attribute
  760.         mov w indicator,'  '    ;indicate no leading stem
  761.         mov si,o left_route    ;load offset to stem string
  762.         cmp b[si],0    ;are there any other routes?
  763.         jne >a1    ;calculate column if there are
  764.         mov al,b this_box    ;load box being written to screen
  765.         and al,b err    ;is there a following box?
  766.         mov al,' '    ;load space
  767.         je >c1    ;check for subchart if not
  768.         mov di,si    ;load offset to start of string
  769.         mov al,'╥'    ;load top stem character
  770.         stosb    ;write it to string
  771.         mov dx,w cursor_pos    ;load cursor coordinates
  772.         jmp >a2    ;increment row marker
  773.  
  774.         ;write jump address for arrow key
  775.  
  776. write_akey_address:
  777.         cmp b this_box,1    ;is box centre box?
  778.         jne ret    ;exit if not
  779.         mov ax,w[bx+akey_addresses]    ;load jump address
  780.         stosw    ;write it to key jump address
  781.         ret    ;exit
  782.  
  783.         ;calculate column for horizontal stem
  784.  
  785. a1:
  786.         mov cx,w left_route_end    ;load offset to end of left route
  787.         sub cx,si    ;calculate length of left route string
  788.         mov dl,40    ;load column of centre of screen
  789.         sub dl,cl    ;calculate length of left route stem
  790.         mov dh,b cursor_pos+1    ;load row
  791. a2:
  792.         mov b indicator,'║'    ;indicate leading stem
  793.         inc b cursor_pos+1    ;increment row
  794.         call cursor    ;position cursor
  795.  
  796.         ;write horizontal stem to screen
  797.  
  798.         mov cx,di    ;load offset to end of string
  799.         sub cx,si    ;calculate length of string
  800. a1:
  801.         lodsb    ;load character from stem string
  802.         call write_chr    ;write it to screen
  803.         loop a1    ;decrement loop count
  804.         inc b stem_start    ;decrement leading stem size
  805.  
  806.         ;create route indicator string for trailing stem
  807.  
  808. b1:
  809.         mov di,o akey_jump    ;load offset to arrow key jump address
  810.         mov dl,'F'    ;load forward route indicator
  811.         mov si,w route_follow    ;load following route for stem
  812.         or si,si    ;is box decision box?
  813.         mov bx,si    ;load offset to forward move address
  814.         je >a1    ;store indicator if not
  815.         mov ax,w box_route    ;load box being written
  816.         mov bx,no    ;load element of box
  817.         call get_box_par    ;get decision box flag
  818.         or ax,ax    ;is box decision box?
  819.         mov bx,ax    ;load offset to forward move address
  820.         je >a1    ;store indicator if not
  821.         mov bx,si    ;load sub offset to jump address
  822.         shr si,1    ;load route indicator
  823.         mov dl,b[si+keys+5]
  824.  
  825.         ;store following box route indicator
  826.  
  827. a1:
  828.         call write_akey_address    ;write arrow key address to table
  829.         mov al,dl    ;load route indicator
  830. c1:
  831.         mov di,o indicator+2    ;load offset to indicator string
  832.         stosb    ;store indicator character
  833.  
  834.         ;check if there is a child subchart from box
  835.  
  836.         mov dx,']['    ;assume subchart is not copied
  837.         mov ax,w box_route    ;load box being written to screen
  838.         mov bx,child    ;load offset to element
  839.         call get_box_par    ;get box child subchart status
  840.         cmp ax,first_box    ;is there a subchart?
  841.         jb >b1    ;terminate indicator string if not
  842.         mov bx,parent    ;load element offset
  843.         call get_box_par    ;get subcharts parent box
  844.         cmp ax,w box_route    ;is subchart copied?
  845. if ne        mov dx,')('    ;load copied subchart brackets if it is
  846.  
  847.         ;write subchart indicator to end of indicator string
  848.  
  849.         mov al,' '    ;load space
  850.         mov ah,dl    ;load open bracket character
  851.         stosw    ;write it to indicator string
  852.         mov al,'D'    ;load option character
  853.         mov ah,dh    ;load close bracket indicator
  854.         stosw    ;write it to end of indicator string
  855.  
  856.         ;terminate indicator string and exit
  857.  
  858. b1:
  859.         xor al,al    ;clear register
  860.         stosb    ;terminate indicator string
  861.         ret    ;exit
  862.  
  863.         ;write message to message buffer
  864.  
  865. write_message:
  866.         xor cx,cx    ;clear count
  867.         mov di,o message    ;load offset to buffer
  868.         mov es,ax,cs    ;copy code segment
  869.         pull si    ;load offset to message string
  870. a1:
  871.         lodsb    ;read character from message string
  872.         or al,al    ;last character?
  873.         je >a2    ;store message length if it is
  874.         inc cx    ;increment message length
  875.         stosb    ;write it to buffer
  876.         jmp a1    ;read next character
  877. a2:
  878.         mov w message_length,cx    ;store message length
  879.         jmp si    ;exit
  880.  
  881.         ;write number in ax:dx to number buffer
  882.  
  883. store_number:
  884.         mov di,o number_buffer    ;load address of buffer    for characters
  885.  
  886.         ;divide number by 10
  887.  
  888. store_number2:
  889.         push bx,dx    ;save registers
  890.         xor dx,dx    ;clear register
  891.         jmp >a1    ;convert number to string
  892. store_number3:
  893.         push bx,dx    ;save registers
  894. a1:
  895.         mov si,di    ;save offset to buffer
  896.  
  897.         ;divide number by 10
  898.  
  899. a3:
  900.         mov w temp3,0      ;initialise remainder
  901.         mov cx,32    ;load iteration count
  902. a1:
  903.         shl ax,1    ;shift low accumulator left one bit
  904.         rcl dx,1    ;shift high accumulator left with carry
  905.         rcl w temp3,1    ;shift third word ieft
  906.         cmp w temp3,10    ;will 10 go into third word?
  907.         jb >a2    ;decrement loop count if not
  908.         sub w temp3,10    ;subtract 10 from accumulator high
  909.         add ax,1    ;increment accumulator
  910.         adc dx,0
  911. a2:
  912.         loop a1    ;decrement loop count
  913.  
  914.         ;store digit in buffer
  915.  
  916.         mov bl,b temp3    ;load remainder
  917.         add bl,48    ;asciiize the remainder
  918.         mov [di],bl    ;store it in number character buffer
  919.         inc di    ;increment pointer
  920.         or ax,dx    ;any more digits?
  921.         jne a3    ;fetch next digit if another digit
  922.  
  923.         ;exit with offset to start of string in si and length in cx
  924.  
  925. a1:
  926.         mov cx,di    ;load offset to end of string
  927.         sub cx,si    ;calculate length of string
  928.         mov bx,di    ;calculate size of string in buffer
  929.         sub bx,o number_buffer
  930.         jc >a1    ;exit if string is not path string
  931.         cmp bx,20    ;is there enough room for string?
  932.         jbe >a1    ;carry on if there is
  933.         sub di,cx    ;restore offset to end of string
  934.         mov b[di],27    ;store marker
  935.         pull dx,bx    ;restore registers
  936.         stc    ;indicate error
  937.         ret    ;exit
  938.  
  939.         ;exit indicating number string copied
  940.  
  941. a1:
  942.         mov si,di    ;load offset to string
  943.         dec si
  944.         pull dx,bx    ;restore registers
  945.         clc    ;indicate ok
  946.         ret    ;exit
  947.  
  948.         ;end
  949.